package service

import (
	"context"
	"errors"
	"github.com/gin-gonic/gin"
	"nearby/biz/common"
	"nearby/biz/config"
	redis "nearby/biz/dal/cache"
	"nearby/biz/domain/aggregate"
	"nearby/biz/domain/entity"
	domainService "nearby/biz/domain/service"
	"nearby/biz/manager/wechat"
	"nearby/biz/model"
	"nearby/biz/util"
)

type WxRegisterService struct {
}

func (ss *WxRegisterService) Execute(ctx *gin.Context, req *model.WxRegisterRequest) (resp *model.WxRegisterResponse, err error) {
	var userService domainService.UserService
	// wx_code换取wx_session
	wxSession, err := userService.GetWxSession(ctx, req.WxCode)
	if err != nil {
		return nil, common.NewBizErr(common.BizErrCode, "GetWxOpenID fail", err)
	}
	if wxSession == nil {
		return nil, common.NewBizErr(common.BizErrCode, "GetWxOpenID fail, the wxSession is nil", err)
	}

	// 查看是否注册过, 如果已注册, 返回错误
	userEntity, err := userService.GetUserEntityByOpenID(ctx, wxSession.OpenID)
	if err != nil {
		return nil, common.NewBizErr(common.BizErrCode, "userService.GetUserEntityByOpenID fail", err)
	}
	if userEntity != nil {
		return nil, common.NewBizErr(common.ReRegisteredErrCode, "user has registered", err)
	}

	// 构造出一个聚合根, 然后对这个聚合根进行持久化
	userAggregate, err := ss.ConstructUserAggregate(ctx, req, wxSession)
	if err != nil {
		return nil, common.NewBizErr(common.BizErrCode, "尝试注册失败", err)
	}
	err = userAggregate.Persist(ctx)
	if err != nil {
		return nil, common.NewBizErr(common.BizErrCode, "userAggregate.Persist fail", err)
	}
	token, err := userAggregate.User.GenerateToken()
	if err != nil {
		return nil, common.NewBizErr(common.BizErrCode, "userAggregate.User.GenerateToken fail", err)
	}
	// todo SetCookie
	//ctx.SetCookie(common.AuthTokenName, token,)
	resp = &model.WxRegisterResponse{
		Meta:           common.MetaOk,
		Token:          token.Token,
		TokenExpiredAt: token.TokenExpiredAt,
	}
	return resp, nil
}

func (ss *WxRegisterService) ConstructUserAggregate(ctx context.Context, req *model.WxRegisterRequest, wxSession *wechat.WxSession) (*aggregate.UserAggregate, error) {
	var userService domainService.UserService
	userID := config.GenerateIDInt64()

	plainData, err := wechat.DecryptData(ctx, wxSession.SessionKey, req.EncryptData, req.IV)
	if err != nil {
		return nil, err
	}
	if plainData == nil && plainData.PhoneNumber == "" {
		return nil, errors.New("手机号为空, 尝试注册失败")
	}
	_ = redis.Set(ctx, "info_open_id_"+wxSession.OpenID, util.ToString(plainData), common.Century)

	userAggregate := &aggregate.UserAggregate{
		User: entity.User{
			UserID: userID,
		},
		UserAccount: entity.UserAccount{
			UserID:      userID,
			PhoneNumber: plainData.PhoneNumber,
			WxOpenID:    wxSession.OpenID,
		},
	}
	// 如果req.HeadURL为空, 则随机生成一个头像
	if req.HeadURL == "" {
		userAggregate.User.HeadURL, _ = userService.GenerateRandomHeadURL(ctx)
	} else {
		userAggregate.User.HeadURL = req.HeadURL
	}
	// 如果req.Nickname为空, 则随机生成一个昵称
	if req.Nickname == "" {
		userAggregate.User.Nickname, _ = userService.GenerateRandomNickname(ctx)
	} else {
		userAggregate.User.Nickname = req.Nickname
	}
	return userAggregate, nil
}
